﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace wontec_claw
{
    class clawhelper
    {
        bool _can = false;
        public List<byte> canBuffer=new List<byte>();
        public Action<int[]> callback=null;

        int step = 0;
        int flag = 0;
        int stats = 0;
        int len = 0;
        int timeout = 0;
        public int canid = 0;
        public byte[] candata = new byte[8];
        public int[] candecode()
        {
            if (_can)
            {
                if(timeout!=0)
                    if (--timeout == 0)
                    {
                        step = 0;
                    }
                while (canBuffer.Count != 0)
                {
                    int dat = canBuffer[0]; canBuffer.RemoveAt(0);
                    timeout = 50;
                    switch (step)
                    {
                        case 0:
                            if (dat == 0xAA)
                                step++;
                            break;
                        case 1:
                            flag = dat;
                            step++;
                            break;
                        case 2:
                            stats = dat;
                            step++;
                            break;
                        case 3:
                            canid = dat;
                            step++;
                            break;
                        case 4:
                            canid |= dat << 8;
                            step++;
                            break;
                        case 5:
                            canid |= dat << 16;
                            step++;
                            break;
                        case 6:
                            canid |= dat << 24;
                            step++;
                            len = 0;
                            break;
                        case 7:
                            if (len != 8)
                            {
                                candata[len] = (byte)dat;
                                len++;
                                if (len == 8) step++;
                            }
                            break;
                        case 8:
                            step = 0;
                            if (dat == 0x55)
                            {
                                return this[canid, candata];
                                //if (callback != null) callback(info);
                            }
                            

                            break;
                    }
                }
                //System.Threading.Thread.Sleep(0);
            }
            return null;
        }

        public bool CANMode
        {
            get { return _can; }
            set {
                _can = value;
                //if (canBuffer != null)
                //{
                //    new System.Threading.Thread(candecode).Start();
                //}

            }
        }
        public static UInt16 cal_crc(string str, int length = -1)
        {
            UInt16 itemp = 0xFFFF;
            byte i;
            int index = 0;
            if (null == str) return 0;
            if (length == -1) length = str.Length;
            while (length-- != 0)
            {
                itemp ^= str[index++];
                for (i = 0; i < 8; i++)
                {
                    if ((itemp & 0x1) != 0)
                    {
                        itemp >>= 1;
                        itemp ^= 0xA001;
                    }
                    else
                    {
                        itemp >>= 1;
                    }
                }
            }
            //itemp = (UInt16)(((itemp << 8) | (itemp >> 8)) & 0xffff);
            return itemp;
        }

        //static byte read8(string hex)
        //{

        //}

        //Dictionary<char, int> keynum = new Dictionary<char, int>();
        Dictionary<char, int> keylen = new Dictionary<char, int>();




        public clawhelper()
        {
            keylen.Add('N', 8 + 2 + 2 + 2 + 1);
            keylen.Add('I', 8 + 2 + 1 + 2);
            keylen.Add('$', 2);
            //keylen.Add('A', 14);
            keylen.Add('g', 2);
            keylen.Add('d', 2);
            //keylen.Add('h', 8+2);
            keylen.Add('B', 2 + 8 + 8 + 8 + 2 + 1 + 8 + 8);
            keylen.Add('R', 8 + 8 + 2 + 1 + 2 + 2 + 4 + 8 + 1);
            keylen.Add('F', 8 + 8 + 8 + 8 + 2);
            keylen.Add('P', 4 + 4 + 4);
            keylen.Add('K', 1);
            keylen.Add('Z', 2);

        }
        int readhex(string str,int num,int offset)
        {
            int index = offset;
            int value = 0;
            while(num--!=0)
            {
                value <<= 4;
                value |= str[index] > '9' ? str[index] - ('A' - 10) : str[index]-'0';
                index++;
            }
            return value;
        }



        public int formatRead(string str,string format,int[] data)
        {
            int readcount = 0;
            int len = format.Length;
            int offset = 0;
            int index = 0;
            int num;
            for(int i = 0;i< format.Length;i++)
            {
                if (format[i] == '%')
                {
                    num = 1;
                    if(format[i + 1]>='0'&& format[i + 1] <= '9')
                    {
                        i++;
                        num = format[i] - '0';
                    }
                    switch (format[i+1])
                    {
                        case 'c':
                            data[index++] = str[offset];
                            break;
                        case 'd':break;
                        case 'x':
                            data[index++] = readhex(str,num, offset);
                            break;
                        case 's':

                            break;
                    }
                    offset += num;
                    i++;
                    readcount++;
                    continue;
                }
                if (format[i] != str[offset])
                {
                    break;
                }
                offset++;
            }
            return readcount;
        }

        public bool Check(string str)
        {
            if (str == null) return false;
            if (str.Length == 0) return false;
            int end = str.IndexOf("\r\n");
            if (end == -1) end = str.Length;
            if (end < 8) return false;
            return str.IndexOf(string.Format("{0:X4}", cal_crc(str,end-4))) == (end - 4);
        }

        public string AppendCRC(string str)
        {
            if (!Check(str))
            {
                str += string.Format("{0:X4}", cal_crc(str));
            }
            return str;
        }

        public byte[] AppendCRCHex(string str)
        {
            if (!Check(str))
            {
                var crcb = new byte[2];
                int crc=cal_crc(str);
                crcb[0]= (byte)(crc&0xff);
                crcb[1] = (byte)((crc>>8) & 0xff);
                return crcb;
            }
            return null;
        }

        public int[] this[string str]
        {
            get {
                var data = new int[11];
                try
                {
                    formatRead(str, ">%2x%c", data);
                    if (keylen.ContainsKey((char)data[1]))
                    {
                        int len = keylen.ContainsKey((char)data[1]) ? keylen[(char)data[1]] : 0;
                        int[] dat = new int[11];
                        dat[0] = data[0];
                        dat[1] = data[1];
                        data = dat;
                        len += 4;
                        int rcrc = (readhex(str, 2, len + 2) | (readhex(str, 2, len) << 8));
                        int lcrc = ((rcrc >> 8) | (rcrc << 8))&0xffff;
                        int crc = cal_crc(str, len);
                        if (crc != rcrc && crc != lcrc)
                        {
                            int endflag = str.IndexOf('\n');
                            if (endflag != -1)
                            {
                                if (endflag > 5)
                                {
                                    if (str[endflag - 1] == '\r') endflag--;
                                    endflag -= 4;
                                    rcrc = (readhex(str, 2, endflag + 2) | (readhex(str, 2, endflag) << 8));
                                    lcrc = ((rcrc >> 8) | (rcrc << 8)) & 0xffff;
                                    if (crc != rcrc && crc != lcrc)
                                        return null;
                                }
                                else
                                    return null;
                            }
                            else
                                return null;
                        }
                    }
                    else
                    {
                        int len = str.Length-1;
                        while (str[len]=='\r'|| str[len] == '\n')
                            len--;
                        int rcrc = (readhex(str, 2, len - 1) | (readhex(str, 2, len - 3) << 8));
                        int lcrc = ((rcrc >> 8) | (rcrc << 8)) & 0xffff;
                        int crc = cal_crc(str, len-3);
                        if (crc != rcrc && crc != lcrc)
                            return null;
                        data[2] = len-3-4;
                    }

                    switch (data[1])
                    {
                        case 'N':
                            if (7 != formatRead(str, ">%2x%c%8x%2x%2x%2x%1x", data))
                                return null;
                            return data;
                        case 'I':
                            if (6 != formatRead(str, ">%2x%c%8x%2x%1x%2x", data))
                                return null;
                            break;
                        case 'A':
                            if (2 != formatRead(str, ">%2x%c", data))
                                return null;
                            break;
                        case 'B':
                            if (10 != formatRead(str, ">%2x%c%2x%8x%8x%8x%2x%1x%8x%8x", data))
                                return null;
                            break;
                        case 'R':
                            if (11 != formatRead(str, ">%2x%c%8x%8x%2x%1x%2x%2x%4x%8x%1x", data))
                                return null;
                            break;
                        case 'F':
                            if (7 != formatRead(str, ">%2x%c%8x%8x%8x%8x%2x", data))
                                return null;
                            break;
                        case 'P':
                            if (5 != formatRead(str, ">%2x%c%4x%4x%4x", data))
                                return null;
                            break;
                        case 'd':
                            if (3 != formatRead(str, ">%2x%c%2x", data))
                                return null;
                            break;
                        case 'g':
                            if (3 != formatRead(str, ">%2x%c%2x", data))
                                return null;
                            break;
                        case 'W':
                            if (7 != formatRead(str, ">%2x%c%2x%2x%8x%8x%8x", data))
                                return null;
                            break;
                        case 'Z':
                            if (3 != formatRead(str, ">%2x%c%2x", data))
                                return null;
                            break;
                        case '$':
                            if (3 != formatRead(str, ">%2x%c%2x", data))
                                return null;
                            break;

                    }
                }
                catch { }
                return data;
            }
            set { }
        }

        int[] lastN;
        byte lastNC;
        int[] lastR;
        byte lastRC;
        int[] lastB;
        byte lastBC;
        int[] lastF;
        byte lastFC;
        int[] lastW;
        byte lastWC;

        public int[] this[byte[] str]
        {
            get { return this[str[8] | (str[9] << 8) | (str[10] << 16) | (str[11] << 24), str]; }
            set { }
        }

        public int[] this[int id,byte[] str]
        {
            get
            {
                var data = new int[3];
                data[0] = id&0xff;
                switch ((id>>8) & 0xff)
                {
                    case 0x00:
                        data[1] = '$';
                        data[2] = str[0];
                        break;
                    case 0x01:
                        data = new int[10];
                        data[0] = id & 0xff;
                        data[1] = 'A';
                        for(int i=0;i<8;i++)
                            data[2+i] = str[i];
                        break;
                    case 0x02:break;
                    case 0x03:
                        data[1] = 'd';
                        data[2] = str[0];
                        break;
                    case 0x04:
                        data = new int[6];
                        data[0] = id & 0xff;
                        data[1] = 'I';
                        data[2] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        data[3] = str[4] | (str[5] << 8);
                        data[4] = str[6];
                        data[5] = str[7];
                        break;
                    case 0x05: break;
                    case 0x06:
                        data[1] = 'i';
                        data[0]= data[2] = str[0];
                        break;
                    case 0x07:
                        data[1] = 'Z';
                        data[2] = str[0];
                        break;
                    case 0x08:
                        data = new int[6];
                        data[0] = id & 0xff;
                        data[1] = 'P';
                        data[2] = str[0] | (str[1] << 8);
                        data[3] = str[2] | (str[3] << 8);
                        data[4] = str[4] | (str[5] << 8);
                        break;
                    case 0x22:
                        data[1] = 'n';
                        break;
                    case 0x23:
                        if(lastN==null)
                            lastN = new int[7];
                        lastN[0] = id & 0xff;
                        lastN[1] = 'N';
                        data = new int[0];

                        if (str[7] == 1) lastNC = 1;
                        else lastNC |= (byte)(1 << (str[7] - 1));
                        if (lastNC == 0x7) data = lastN;

                        if (str[7]==1)
                            lastN[2] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 2)
                            lastN[3] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 3)
                        {
                            lastN[4] = str[0];
                            lastN[5] = str[1] | (str[2] << 8);
                            lastN[6] = str[3];
                        }
                        break;
                    case 0x34:
                        data[1] = 'r';
                        break;
                    case 0x35:
                        if (lastR == null)
                            lastR = new int[11];
                        lastR[0] = id & 0xff;
                        lastR[1] = 'R';
                        data = new int[0];

                        if (str[7] == 1) lastRC = 1;
                        else lastRC |= (byte)(1 << (str[7] - 1));
                        if (lastRC == 0x3f) data = lastR;

                        if (str[7] == 1)
                            lastR[2] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 2)
                            lastR[3] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 3)
                            lastR[4] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 4)
                            lastR[8] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 5)
                            lastR[9] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 6)
                        {
                            lastR[5] = str[0];
                            lastR[6] = str[1];
                            lastR[7] = str[2];
                            lastR[10] = str[3];
                            //data = lastR;
                        }
                        break;
                    case 0x41:
                        data[1] = 'b';
                        break;
                    case 0x42:
                        if (lastB == null)
                            lastB = new int[10];
                        lastB[0] = id & 0xff;
                        lastB[1] = 'B';
                        data = new int[0];

                        if (str[7] == 1) lastBC = 1;
                        else lastBC |= (byte)(1 << (str[7] - 1));
                        if (lastBC == 0x3f) data = lastB;

                        if (str[7] == 1)
                            lastB[3] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 2)
                            lastB[4] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 3)
                            lastB[5] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 4)
                            lastB[8] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 5)
                            lastB[9] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 6)
                        {
                            lastB[2] = str[0];
                            lastB[6] = str[1];
                            lastB[7] = str[2];
                            //data = lastB;
                        }
                        break;
                    case 0x44:
                        data[1] = 'g';
                        data[2] = str[0];
                        break;
                    case 0x51:
                        data[1] = 'f';
                        break;
                    case 0x52:
                        if (lastF == null)
                            lastF = new int[7];
                        lastF[0] = id & 0xff;
                        lastF[1] = 'F';
                        data = new int[0];

                        if (str[7] == 1) lastFC = 1;
                        else lastFC |= (byte)(1 << (str[7] - 1));
                        if (lastFC == 0xf) data = lastF;

                        if (str[7] == 1)
                            lastF[2] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 2)
                            lastF[3] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 3)
                            lastF[4] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 4)
                        {
                            lastF[5] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                            lastF[6] = str[4];
                            //data = lastF;
                        }
                        break;
                    case 0x25://W 返回
                        if (lastW == null)
                            lastW = new int[7];
                        lastW[0] = id & 0xff;
                        lastW[1] = 'W';
                        data = new int[0];

                        if (str[7] == 1) lastWC = 1;
                        else lastWC |= (byte)(1 << (str[7] - 1));
                        if (lastWC == 0x3) data = lastW;

                        if (str[7] == 1)
                            lastW[2] = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24);
                        if (str[7] == 2)
                            lastW[3] = str[0];

                        break;
                    case 0x24:
                        data[1] = 'w';
                        break;
                }
                return data;
            }
            set { }
        }

        private byte CRC_8(byte[] source,int offset, int len)
        {
            byte b = 0;
            int num = 0;
            while (len-- != 0)
            {
                b ^= source[num];
                num++;
                for (int i = 0; i < 8; i++)
                {
                    bool flag = (b & 1) == 1;
                    if (flag)
                    {
                        b = (byte)(b >> 1 ^ 140);
                    }
                    else
                    {
                        b = (byte)(b >> 1);
                    }
                }
            }
            return b;
        }
        byte[] canData = { 0x55 ,0xAA ,0x1E, 0x03, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0 };
        object buildcanpacket2(int id,params byte[] data)
        {
            int count = (data.Length + 7) / 8;
            if (count == 0) count = 1;
            int offset = 0;
            int index = 0;
            int mulindex = 0;
            byte[] bytes=null;
            byte[][] mulbytes = new byte[count][];
            while (count-- != 0)
            {
                bytes = new byte[canData.Length];
                for (int i = 0; i < canData.Length; i++)
                    bytes[i + offset] = canData[i];

                bytes[offset + 13] = (byte)((id >> 0) & 0xff);
                bytes[offset + 14] = (byte)((id >> 8) & 0xff);
                bytes[offset + 15] = (byte)((id >> 16) & 0xff);
                bytes[offset + 16] = (byte)((id >> 24) & 0xff);

                for (int i = 0; i < 8; i++)
                {
                    if (index == data.Length) break;
                    bytes[offset + 21 + i] = data[index++];
                }

                bytes[offset+canData.Length-1]=CRC_8(bytes, offset, canData.Length);
                //offset += canData.Length;
                mulbytes[mulindex++] = bytes;
            }
            if (mulbytes.Length == 1) return bytes;
            return mulbytes;
        }

        object buildcanpacket(int id, params byte[] data)
        {
            int count = (data.Length + 7) / 8;
            if (count == 0) count = 1;
            int offset = 0;
            int index = 0;
            int mulindex = 0;
            byte[] bytes = null;
            byte[][] mulbytes = new byte[count][];
            while (count-- != 0)
            {
                bytes = new byte[12];
                bytes[8] = (byte)((id >> 0) & 0xff);
                bytes[9] = (byte)((id >> 8) & 0xff);
                bytes[10] = (byte)((id >> 16) & 0xff);
                bytes[11] = (byte)((id >> 24) & 0xff);

                for (int i = 0; i < 8; i++)
                {
                    if (index == data.Length) break;
                    bytes[i] = data[index++];
                }

                //offset += canData.Length;
                mulbytes[mulindex++] = bytes;
            }
            if (mulbytes.Length == 1) return bytes;
            return mulbytes;
        }

        public object this[char cmd,int id=0,params int[] data]
        {
            get {
                if (CANMode)
                {
                    int canid;
                    object bytes=null;
                    try
                    {
                        switch (cmd)
                        {
                            case 'N':
                                canid = 0x00002300 + id;
                                bytes = buildcanpacket(canid);
                                break;
                            case 'n':
                                canid = 0x00002200 + id;
                                bytes = buildcanpacket(
                                    canid,
                                    (byte)((data[0] >> 0) & 0xff), (byte)((data[0] >> 8) & 0xff), (byte)((data[0] >> 16) & 0xff), (byte)((data[0] >> 24) & 0xff),
                                    0,0,0,1,
                                    (byte)((data[1] >> 0) & 0xff), (byte)((data[1] >> 8) & 0xff), (byte)((data[1] >> 16) & 0xff), (byte)((data[1] >> 24) & 0xff),
                                    0,0,0,2,
                                    (byte)data[2], (byte)data[3], 0, (byte)data[4],
                                    0,0,0,3
                                    );
                                break;
                            case 'I':
                                canid = 0x00000400 + id;
                                bytes = buildcanpacket(canid);
                                break;
                            case '$':
                                canid = 0x00000000;
                                bytes = buildcanpacket(canid);
                                break;
                            case 'A':
                                canid = 0x00000100 + id;
                                bytes = buildcanpacket(canid);
                                break;
                            case 'a':
                                canid = 0x00000200 + id;
                                bytes = buildcanpacket(canid,(byte)data[0]);
                                break;
                            case 'b':
                                canid = 0x00004100 + id;
                                bytes = buildcanpacket(
                                    canid,
                                    (byte)((data[1] >> 0) & 0xff), (byte)((data[1] >> 8) & 0xff), (byte)((data[1] >> 16) & 0xff), (byte)((data[1] >> 24) & 0xff),
                                    0, 0, 0, 1,
                                    (byte)((data[2] >> 0) & 0xff), (byte)((data[2] >> 8) & 0xff), (byte)((data[2] >> 16) & 0xff), (byte)((data[2] >> 24) & 0xff),
                                    0, 0, 0, 2,
                                    (byte)((data[3] >> 0) & 0xff), (byte)((data[3] >> 8) & 0xff), (byte)((data[3] >> 16) & 0xff), (byte)((data[3] >> 24) & 0xff),
                                    0, 0, 0, 3,
                                    (byte)((data[6] >> 0) & 0xff), (byte)((data[6] >> 8) & 0xff), (byte)((data[6] >> 16) & 0xff), (byte)((data[6] >> 24) & 0xff),
                                    0, 0, 0, 4,
                                    (byte)((data[7] >> 0) & 0xff), (byte)((data[7] >> 8) & 0xff), (byte)((data[7] >> 16) & 0xff), (byte)((data[7] >> 24) & 0xff),
                                    0, 0, 0, 5,
                                    (byte)data[0], (byte)data[4], (byte)data[5],0,
                                    0, 0, 0, 6
                                    );
                                break;
                            case 'B':
                                canid = 0x00004200 + id;
                                bytes = buildcanpacket(canid);
                                break;
                            case 'd':
                                canid = 0x00000300 + id;
                                bytes = buildcanpacket(canid);
                                break;
                            case 'D':
                                canid = 0x00003200 + id;
                                bytes = buildcanpacket(canid,(byte)((data[0]>>0)&0xff), (byte)((data[0] >> 8) & 0xff), (byte)((data[0] >> 16) & 0xff), (byte)((data[0] >> 24) & 0xff));
                                break;
                            case 'E':
                                canid = 0x00002100 + id;
                                bytes = buildcanpacket(canid, (byte)data[0]);
                                break;
                            case 'f':
                                canid = 0x00005100 + id;
                                bytes = buildcanpacket(
                                    canid,
                                    (byte)((data[0] >> 0) & 0xff), (byte)((data[0] >> 8) & 0xff), (byte)((data[0] >> 16) & 0xff), (byte)((data[0] >> 24) & 0xff),
                                    0, 0, 0, 1,
                                    (byte)((data[1] >> 0) & 0xff), (byte)((data[1] >> 8) & 0xff), (byte)((data[1] >> 16) & 0xff), (byte)((data[1] >> 24) & 0xff),
                                    0, 0, 0, 2,
                                    (byte)((data[2] >> 0) & 0xff), (byte)((data[2] >> 8) & 0xff), (byte)((data[2] >> 16) & 0xff), (byte)((data[2] >> 24) & 0xff),
                                    0, 0, 0, 3,
                                    (byte)((data[3] >> 0) & 0xff), (byte)((data[3] >> 8) & 0xff), (byte)((data[3] >> 16) & 0xff), (byte)((data[3] >> 24) & 0xff),
                                    (byte)data[4], 0, 0, 4
                                    );
                                break;
                            case 'F':
                                canid = 0x00005200 + id;
                                bytes = buildcanpacket(canid);
                                break;
                            case 'j':
                                canid = 0x00005300 + id;
                                bytes = buildcanpacket(
                                    canid, 
                                    (byte)((data[0] >> 0) & 0xff), (byte)((data[0] >> 8) & 0xff), (byte)((data[0] >> 16) & 0xff), (byte)((data[0] >> 24) & 0xff),
                                    (byte)((data[1] >> 0) & 0xff), (byte)((data[1] >> 8) & 0xff), (byte)((data[1] >> 16) & 0xff), (byte)((data[1] >> 24) & 0xff)
                                    );

                                break;
                            case 'G':
                                canid = 0x00004300 + id;
                                bytes = buildcanpacket(canid);
                                break;
                            case 'g':
                                canid = 0x00004400 + id;
                                bytes = buildcanpacket(canid);
                                break;
                            case 'h':
                                canid = 0x00003100 + id;
                                bytes = buildcanpacket(
                                    canid,
                                    (byte)((data[0] >> 0) & 0xff), (byte)((data[0] >> 8) & 0xff), (byte)((data[0] >> 16) & 0xff), (byte)((data[0] >> 24) & 0xff),
                                    (byte)data[1]
                                    );
                                break;
                            case 'i':
                                canid = 0x00000600 + id;
                                bytes = buildcanpacket(canid, (byte)data[0]);
                                break;
                            case 'm':
                                canid = 0x00005400 + id;
                                bytes = buildcanpacket(canid, (byte)((data[0] >> 0) & 0xff), (byte)((data[0] >> 8) & 0xff), (byte)((data[0] >> 16) & 0xff), (byte)((data[0] >> 24) & 0xff));
                                break;
                            case 'r':
                                canid = 0x00003400 + id;
                                bytes = buildcanpacket(
                                    canid,
                                    (byte)((data[0] >> 0) & 0xff), (byte)((data[0] >> 8) & 0xff), (byte)((data[0] >> 16) & 0xff), (byte)((data[0] >> 24) & 0xff),
                                    0, 0, 0, 1,
                                    (byte)((data[1] >> 0) & 0xff), (byte)((data[1] >> 8) & 0xff), (byte)((data[1] >> 16) & 0xff), (byte)((data[1] >> 24) & 0xff),
                                    0, 0, 0, 2,
                                    (byte)((data[2] >> 0) & 0xff), (byte)((data[2] >> 8) & 0xff), (byte)((data[2] >> 16) & 0xff), (byte)((data[2] >> 24) & 0xff),
                                    0, 0, 0, 3,
                                    (byte)((data[6] >> 0) & 0xff), (byte)((data[6] >> 8) & 0xff), (byte)((data[6] >> 16) & 0xff), (byte)((data[6] >> 24) & 0xff),
                                    0, 0, 0, 4,
                                    (byte)((data[7] >> 0) & 0xff), (byte)((data[7] >> 8) & 0xff), (byte)((data[7] >> 16) & 0xff), (byte)((data[7] >> 24) & 0xff),
                                    0, 0, 0, 5,
                                    (byte)data[3], (byte)data[4], (byte)data[5], (byte)data[8],
                                    0, 0, 0, 6
                                    );
                                break;
                            case 'R':
                                canid = 0x00003500 + id;
                                bytes = buildcanpacket(canid);
                                break;
                            case 'p':
                                canid = 0x00000900 + id;
                                bytes = buildcanpacket(canid, 
                                    (byte)((data[0] >> 0) & 0xff), (byte)((data[0] >> 8) & 0xff), 
                                    (byte)((data[1] >> 0) & 0xff), (byte)((data[1] >> 8) & 0xff),
                                    (byte)((data[2] >> 0) & 0xff), (byte)((data[2] >> 8) & 0xff)
                                    );
                                break;
                            case 'P':
                                canid = 0x00000800 + id;
                                bytes = buildcanpacket(canid);
                                break;
                            case 'U':
                                canid = 0x00000500 + id;
                                bytes = buildcanpacket(canid);
                                break;
                            case 'Z':
                                canid = 0x00000700 + id;
                                bytes = buildcanpacket(canid);
                                break;
                            case 'K':
                                canid = 0x00003300 + id;
                                bytes = buildcanpacket(canid, (byte)data[0]);
                                break;
                            case 'Q':
                                canid = 0x00001100 + id;
                                bytes = buildcanpacket(canid);
                                break;
                            case 'w':
                                canid = 0x00002400 + id;
                                bytes = buildcanpacket(
                                    canid,
                                    (byte)((data[0] >> 0) & 0xff), (byte)((data[0] >> 8) & 0xff), (byte)((data[0] >> 16) & 0xff), (byte)((data[0] >> 24) & 0xff),
                                    0, 0, 0, 1,
                                    (byte)((data[1] >> 0) & 0xff), 0, 0, 0,
                                    0, 0, 0, 2
                                    );
                                break;
                            case 'W':
                                canid = 0x00002500 + id;
                                bytes = buildcanpacket(canid);
                                break;
                        }
                    }
                    catch { }


                    return bytes;
                }
                string str="";
                try
                {
                    switch (cmd)
                    {
                        case 'N':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case 'n':
                            str = string.Format(">{0:X2}{1}{2:X8}{3:X2}{4:X2}{5:X2}{6}", id, cmd, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
                            break;
                        case 'I':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case '$':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case 'A':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case 'a':
                            str = string.Format(">{0:X2}{1}{2:X1}", id, cmd, data[0]);
                            break;
                        case 'b':
                            str = string.Format(">{0:X2}{1}{2:X2}{3:X8}{4:X8}{5:X8}{6:X2}{7}{8:X8}{9:X8}", id, cmd, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
                            break;
                        case 'B':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case 'd':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case 'D':
                            str = string.Format(">{0:X2}{1}{2:X8}", id, cmd, data[0]);
                            break;
                        case 'E':
                            str = string.Format(">{0:X2}{1}{2:X1}", id, cmd, data[0]);
                            break;
                        case 'f':
                            str = string.Format(">{0:X2}{1}{2:X8}{3:X8}{4:X8}{5:X8}{6:X2}", id, cmd, data[0], data[1], data[2], data[3],data[4]);
                            break;
                        case 'F':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case 'j':
                            str = string.Format(">{0:X2}{1}{2:X8}{3:X8}", id, cmd, data[0], data[1]);
                            break;
                        case 'G':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case 'g':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case 'h':
                            str = string.Format(">{0:X2}{1}{2:X8}{3:X2}", id, cmd,data[0],data[1]);
                            break;
                        case 'i':
                            str = string.Format(">{0:X2}{1}{2:X2}", id, cmd, data[0]);
                            break;
                        case 'm':
                            str = string.Format(">{0:X2}{1}{2:X8}", id, cmd, data[0]);
                            break;
                        case 'r':
                            str = string.Format(">{0:X2}{1}{2:X8}{3:X8}{4:X2}{5:X1}{6:X2}{7:X2}{8:X4}{9:X8}{10:X1}", id, cmd, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]);
                            break;
                        case 'R':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case 'p':
                            str = string.Format(">{0:X2}{1}{2:X4}{3:X4}{4:X4}", id, cmd, data[0], data[1], data[2]);
                            break;
                        case 'P':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case 'U':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case 'Z':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case 'K':
                            str = string.Format(">{0:X2}{1}{2:X1}", id, cmd, data[0]);
                            break;
                        case 'Q':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case 'W':
                            str = string.Format(">{0:X2}{1}", id, cmd);
                            break;
                        case 'w':
                            str = string.Format(">{0:X2}{1}{2:X2}{3:X2}{4:X8}{5:X8}{6:X8}", id, cmd,data[0],data[1],0,0,0);
                            break;
                    }
                }
                catch { }
                if (str.Length != 0)
                {
                    str += string.Format("{0:X4}", cal_crc(str));
                    str += "\r\n";
                }
                return str; }
            set {
            }
        }
        


    }
}

